﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using Windows.Devices.Geolocation;
using ODS.Config;
using System.Windows.Threading;
using Microsoft.Phone.Maps.Controls;
using System.Collections.ObjectModel;
using System.Device.Location;
using System.Windows.Media.Imaging;
using ODS.Model;

namespace ODS.UserControls
{
    public partial class ChooseLocationView : UserControl
    {
        public SettingPage parrentPage;

        Place myPlace;
        Place currentSelectedPlace;

        bool isClickBtnGetLocation = false;
        String addressHasJustSearch = "";

        private DispatcherTimer timerSearchLocation = new DispatcherTimer();
        MapLayer layerPushPin = new MapLayer();
        MapOverlay overlayForMyLocation = null;
        MapOverlay overlayUserTouched = null;

        ObservableCollection<us_SearchResultItem> ListSearchPlace;

        public event Action<Place> OnGetGeocodingLocation;

        public ChooseLocationView()
        {
            InitializeComponent();

            myPlace = new Place();
            currentSelectedPlace = new Place();

            map.Layers.Add(layerPushPin);

            timerSearchLocation.Tick += timerSearchLocation_Tick;

            ListSearchPlace = new ObservableCollection<us_SearchResultItem>();
            lls_resultLocation.ItemsSource = ListSearchPlace;
        }

        void releaseTimer()
        {
            timerSearchLocation.Stop();
            timerSearchLocation.Tick -= timerSearchLocation_Tick;
            timerSearchLocation = null;
        }

        /// <summary>
        /// Add single push pin on map
        /// </summary>
        /// <param name="pin"></param>
        public void AddPushPin(double Lattitude, double Longitude)
        {
            if (overlayUserTouched == null)
            {
                overlayUserTouched = new MapOverlay();
                Image image = new Image();
                image.Source = new BitmapImage(new Uri(@"/Assets/images/Location selection.png", UriKind.Relative));
                overlayUserTouched.Content = image;
                layerPushPin.Add(overlayUserTouched);
            }

            overlayUserTouched.GeoCoordinate = new GeoCoordinate(Lattitude, Longitude);

        }

        public void AddPushPinForMyCurrentLocation(double Lattitude, double Longitude)
        {
            if (overlayForMyLocation == null)
            {
                overlayForMyLocation = new MapOverlay();
                Image image = new Image();
                image.Source = new BitmapImage(new Uri(@"/Assets/images/person.png", UriKind.Relative));
                overlayForMyLocation.Content = image;
                layerPushPin.Add(overlayForMyLocation);
            }

            overlayForMyLocation.GeoCoordinate = new GeoCoordinate(Lattitude, Longitude);

        }

        public async void getMyLocation()
        {
            Geolocator geolocator = new Geolocator();
            geolocator.DesiredAccuracyInMeters = 50;

            try
            {
                Geoposition geoposition = await geolocator.GetGeopositionAsync(
                    maximumAge: TimeSpan.FromMinutes(5),
                    timeout: TimeSpan.FromSeconds(10)
                    );

                myPlace.Longitude = geoposition.Coordinate.Longitude;
                myPlace.Lattitude = geoposition.Coordinate.Latitude;

                currentSelectedPlace.Lattitude = myPlace.Lattitude;
                currentSelectedPlace.Longitude = myPlace.Longitude;

                GoogleServiceHandler googleService = new GoogleServiceHandler();
                googleService.OnGetGeocodingLocation += googleService_OnGetPlaceByLatLng;
                googleService.GetPlaceByLatLng(currentSelectedPlace.Lattitude, currentSelectedPlace.Longitude);

                AddPushPinForMyCurrentLocation(geoposition.Coordinate.Latitude, geoposition.Coordinate.Longitude);
                map.SetView(new GeoCoordinate(geoposition.Coordinate.Latitude, geoposition.Coordinate.Longitude, 200), 11);


            }
            catch (Exception ex)
            {
                if ((uint)ex.HResult == 0x80004004)
                {
                    // the application does not have the right capability or the location master switch is off
                    //MessageBox.Show("GPS is disabled, this may cause the Puddy app to fail.");
                    //toast.Show("GPS is disabled, this may cause the Puddy app to fail.");
                    if (isClickBtnGetLocation)
                        MessageBox.Show(Constants.MES_TURN_OFF_LOCATION);
                }
                else
                {
                    // something else happened acquring the location
                }
            }
        }


        private void showWaiting()
        {
            pg_waiting.Visibility = Visibility.Visible;
        }

        private void hideWaiting()
        {
            pg_waiting.Visibility = Visibility.Collapsed;
        }

        private void searchLocation()
        {
            timerSearchLocation.Stop();
            timerSearchLocation.Interval = new TimeSpan(0, 0, 3);
            timerSearchLocation.Start();

        }

        void timerSearchLocation_Tick(object sender, EventArgs e)
        {
            startSearch();
        }

        private void startSearch()
        {
            if (tb_address.MyText != "")
            {
                showWaiting();
                timerSearchLocation.Stop();

                ListSearchPlace.Clear();

                addressHasJustSearch = tb_address.MyText;

                String str_lat, str_lng;
                if (myPlace == null)
                {
                    str_lat = "0.0";
                    str_lng = "0.0";
                }
                else
                {
                    str_lat = myPlace.Lattitude.ToString();
                    str_lng = myPlace.Longitude.ToString();
                }

                GoogleServiceHandler service = new GoogleServiceHandler();
                service.GetPlaceByKeyWord(tb_address.MyText);
                service.OnGetPlace += googleService_OnGetPlace;
            }

        }

        void googleService_OnGetPlace(List<Place> places)
        {
            bool hasData = false;
            if (places != null)
            {
                if (places.Count > 0)
                    hasData = true;
                addPlaces(places);
            }


            hideWaiting();
            if (!hasData)
                toast.Show("Search no result");


        }

        void addPlaces(List<Place> places)
        {
            if (places.Count > 0)
            {
                //map.Visibility = Visibility.Collapsed;
                lls_resultLocation.Visibility = Visibility.Visible;

                foreach (Place place in places)
                {
                    us_SearchResultItem item = new us_SearchResultItem();
                    item.setAddress(place.Address);
                    item.Tag = place;

                    Dispatcher.BeginInvoke(() =>
                    {
                        ListSearchPlace.Add(item);
                    });

                }
            }
            else
            {
                //map.Visibility = Visibility.Visible;
                lls_resultLocation.Visibility = Visibility.Collapsed;
            }

        }

        

        private void btn_getCurrentLocation_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            lls_resultLocation.Visibility = Visibility.Collapsed;
            //map.Visibility = Visibility.Visible;

            isClickBtnGetLocation = true;
            getMyLocation();
        }

        private void tb_address_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
        {
            if (tb_address.MyText != "")
            {
                if (tb_address.MyText != addressHasJustSearch)
                    searchLocation();
            }
            else
            {
                //map.Visibility = Visibility.Visible;
                lls_resultLocation.Visibility = Visibility.Collapsed;

                addressHasJustSearch = "";
            }

        }

        private void lls_resultLocation_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            if (lls_resultLocation.SelectedItem == null)
                return;

            Place place = (lls_resultLocation.SelectedItem as us_SearchResultItem).Tag as Place;
            addressHasJustSearch = place.Address;

            AddPushPin(place.Lattitude, place.Longitude);
            map.SetView(new GeoCoordinate(place.Lattitude, place.Longitude, 200), 9);

            currentSelectedPlace = place;

            tbl_address.Text = place.Address;
            tbl_latlng.Text = String.Format("({0}, {1})", place.Lattitude, place.Longitude);

            //map.Visibility = Visibility.Visible;
            lls_resultLocation.Visibility = Visibility.Collapsed;
        }

        private void map_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            Point p = e.GetPosition(this.map);
            GeoCoordinate geo = new GeoCoordinate();
            geo = map.ConvertViewportPointToGeoCoordinate(p);

            showWaiting();

            GoogleServiceHandler service = new GoogleServiceHandler();
            service.GetPlaceByLatLng(geo.Latitude, geo.Longitude);
            service.OnGetGeocodingLocation += googleService_OnGetPlaceByLatLng;

            AddPushPin(geo.Latitude, geo.Longitude);
        }

        void googleService_OnGetPlaceByLatLng(String address, double lat, double lng)
        {
            hideWaiting();

            if (address != null)
            {
                tbl_address.Text = address;
                tbl_latlng.Text = String.Format("({0}, {1})", lat, lng);
                addressHasJustSearch = address;

                if (currentSelectedPlace == null)
                    currentSelectedPlace = new Place();
                currentSelectedPlace.Address = address;
                currentSelectedPlace.Lattitude = lat;
                currentSelectedPlace.Longitude = lng;
            }


        }

        private void btn_cancel_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            this.parrentPage.hiddenChooseLocationViewWithAnimation();
        }

        private void btn_apply_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            this.parrentPage.hiddenChooseLocationViewWithAnimation();

            if (currentSelectedPlace == null)
            {
                toast.Show("Please select location!");
                return;
            }

            OnGetGeocodingLocation(currentSelectedPlace);
        }

    }
}
